﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace Clotho {
	public class CmdRecord {
		readonly Stack<(Action cmd, Action ant_cmd)> undo_stack = new Stack<(Action, Action)>();
		readonly Stack<(Action cmd, Action ant_cmd)> redo_stack = new Stack<(Action, Action)>();
		public CmdRecord(){}
		public void doCmd(Action cmd, Action ant_cmd) {
			undo_stack.Push((cmd, ant_cmd));
			cmd.Invoke();
			redo_stack.Clear();
		}
		public void addCmdKnot() {
			undo_stack.Push((null, null));
		}
		public bool doStackMove(
			Stack<(Action cmd, Action ant_cmd)> from, 
			Stack<(Action cmd, Action ant_cmd)> to,
			Action<(Action cmd, Action ant_cmd)> docmd) {
			if (from.Count == 0) {
				return false;
			}
			to.Push((null, null));
			while (true) {
				var cmd = from.Pop();
				if (cmd.ant_cmd != null) {
					docmd(cmd);
					to.Push(cmd);
				} else {
					return true;
				}
			}
		}
		public bool undo() {
			return doStackMove(undo_stack, redo_stack,cmd=>cmd.ant_cmd());
		}
		public bool redo() {
			return doStackMove(redo_stack, undo_stack, cmd => cmd.cmd());
		}
	}
	/// <summary>
	/// 表示在一串用户操作出现了一条无法执行的操作
	/// </summary>
	public class InvalidCmd_Exception : Exception {
		IItem item;
		public InvalidCmd_Exception(IItem item) {
			this.item = item;
		}

		public InvalidCmd_Exception(IItem item,string message) : base(message) {
			this.item = item;
		}

		public InvalidCmd_Exception(IItem item,string message, Exception innerException) : base(message, innerException) {
			this.item = item;
		}

		protected InvalidCmd_Exception(IItem item,  SerializationInfo info, StreamingContext context) : base(info, context) {
			this.item = item;
		}
	}
	}
